package messangerServer;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import messangerTypes.MessangerSettings;
import messangerTypes.MultiCastAnouncement;
import messangerTypes.User;

public class MulticastWorker extends Thread
{
	private final MultiCastAnouncement ma = new MultiCastAnouncement();
	private final Object lock = new Object();
	private MulticastSocket sock;
	//using a semaphore eliminates the change of missing an update because i was busy.
	private Semaphore sem = new Semaphore(0);
	public boolean quit = false;
	
	
	public MulticastWorker() throws IOException
	{
		this.sock = new MulticastSocket();
	}
	
	public void addUser (User user)
	{
		//send on change
		synchronized (lock)
		{
			ma.addUser(user);
		}
		sem.release();
	}
	
	public void removeUser (int userId)
	{
		//send on change
		synchronized (lock)
		{
			//ugh loop locking a mutex....
			for(int i = 0; i < ma.getActiveUsers().size(); i++)
			{
				if(ma.getActiveUsers().get(i).getId() == userId)
				{
					ma.getActiveUsers().remove(i);
					break;
				}
				else
				{
					//move on
				}
			}
		}
		sem.release();
	}
	
	public void run ()
	{
		byte [] buffer = null;
		DatagramPacket packet = null;
		while(!quit)
		{
			try
			{
				if(sem.tryAcquire(250, TimeUnit.MILLISECONDS))
				{
					System.out.println("Sending mulitcast.");
					synchronized (lock)
					{
						buffer = ma.getBytes();
						packet = new DatagramPacket(buffer, buffer.length,
								InetAddress.getByName(MessangerSettings.getMulticastaddress()), 
								MessangerSettings.getMcastport());
					}
					sock.send(packet);					
				}
				else
				{
					
				}
			} catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public MultiCastAnouncement getMa()
	{
		synchronized (lock)
		{
			return ma;
		}
	}
}
